﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Web.Security;
using System.Globalization;
using System.IO;


namespace Utils
{
    public class Encryption
    {
        public Encryption()
        {

        }
        /// <summary>
        /// MD5 encryption method
        /// </summary>
        /// <returns>MD5 encryption results</returns>
        public static string EncryptMD5(string oldData)
        {
            //Will OldData encoding for a byte sequence. 
            Byte[] clearBytes = new UnicodeEncoding().GetBytes(oldData);
            //Calculating the hash value byte array.
            Byte[] hashedBytes = ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(clearBytes);
            //Return string MD5 encrypted ciphertext
            return BitConverter.ToString(hashedBytes);
        }

        /// <summary>
        /// SHA1 encryption method
        /// </summary>
        /// <param name="oldData">Want to encrypt the original text</param>
        /// <returns>SHA1 encryption results</returns>
        public static string EncryptSHA1(string oldData)
        {
            //According to SHA1 hash algorithm to generate a password hash. 
            string sha1EncryptString = FormsAuthentication.HashPasswordForStoringInConfigFile(oldData, "SHA1");
            return sha1EncryptString;
        }

        /// <summary>
        /// DESencryption method
        /// </summary>
        /// <param name="oldData">Want to encrypt the original text</param>
        /// <returns>DES encryption results</returns>
        /// 
        public static string EncryptDES(string oldData)
        {
            string key = @"??^&$%^&"; // Encryption key
            //Will be designated OldData all character encoding for a byte sequence.
            byte[] data = Encoding.UTF8.GetBytes(oldData);

            //Instantiate a DESCryptoServiceProvider
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();

            //Access to or set up Data Encryption Standard (des) algorithm secret key
            des.Key = ASCIIEncoding.ASCII.GetBytes(key);

            //DES algorithm to obtain or set the initialization vector (IV). (From SymmetricAlgorithm succession.)
            des.IV = ASCIIEncoding.ASCII.GetBytes(key);

            //Create a symmetric Data Encryption Standard (des) encryption object
            ICryptoTransform desencrypt = des.CreateEncryptor();

            //Calculation of specified byte array conversion designated area
            byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
            return BitConverter.ToString(result);
        }

        /// <summary>
        /// DES decryption methods
        /// </summary>
        /// <param name="oldData">To decrypt the original text</param>
        /// <returns>DES decryption results</returns>

        public static string DecodeDES(string oldData)
        {
            try
            {
                string key = @"??^&$%^&"; //decryption key
                //Back to contain OldData in sub-string (from "-" delimited) array of String。 
                string[] inputData = oldData.Split("-".ToCharArray());
                byte[] data = new byte[inputData.Length];
                for (int i = 0; i < inputData.Length; i++)
                {
                    data[i] = byte.Parse(inputData[i], NumberStyles.HexNumber);
                }
                //Instantiate a DESCryptoServiceProvider
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();

                //Access to or set up Data Encryption Standard (des) algorithm secret key 
                des.Key = ASCIIEncoding.ASCII.GetBytes(key);

                //DES algorithm to obtain or set the initialization vector (IV). (From SymmetricAlgorithm succession.)
                des.IV = ASCIIEncoding.ASCII.GetBytes(key);

                //Create a symmetric Data Encryption Standard (des) encryption object
                ICryptoTransform desencrypt = des.CreateDecryptor();

                //Calculation of specified byte array conversion designated area
                byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
                return Encoding.UTF8.GetString(result);
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 用來加密url參數
        /// </summary>
        /// <param name="strToEncrypt"></param>
        /// <returns></returns>
        public static string UrlEncrypt(string strToEncrypt)
        {
            string strEncryptKey = @"??^&$%^&";
            Byte[] key;
            Byte[] IV = new Byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
            try
            {



                key = Encoding.UTF8.GetBytes(strEncryptKey.Substring(0, 8));
                Byte[] inputByteArray = Encoding.UTF8.GetBytes(strToEncrypt);

                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(key, IV), CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();

                return Convert.ToBase64String(ms.ToArray());
            }
            catch
            {
                return string.Empty;
            }

        }

        /// <summary>
        /// 用來解密url參數
        /// </summary>
        /// <param name="strToDecrypt"></param>
        /// <returns></returns>
        public static string UrlDecrypt(string strToDecrypt)
        {
            Byte[] key;
            Byte[] IV = new Byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
            string strEncryptKey = @"??^&$%^&";
            try
            {
                key = Encoding.UTF8.GetBytes(strEncryptKey.Substring(0, 8));
                Byte[] inputByteArray = Convert.FromBase64String(strToDecrypt);

                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(key, IV), CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();

                return Encoding.UTF8.GetString(ms.ToArray());
            }
            catch
            {
                return string.Empty;
            }
        }

        #region RC4算法 for IOC
        /// <summary>
        /// RC4加密解密方法
        /// </summary>
        /// <param name="DataString">待处理string</param>
        /// <param name="EncodeString">密钥</param>
        /// <returns>密文</returns>
        public static string Rc4EncryptMethod(string DataString)
        {
            string EncodeKeyString = "wsiosviolet";
            int[] intArray = new int[256];
            char[] charArray = new char[256];
            int int_j = 0;
            int int_i = 0;

            for (int i = 0; i < 256; i++)
            {
                intArray[i] = i;
            }
            int_j = 1;
            for (short i = 0; i < 256; i++)
            {
                char c = EncodeKeyString.ToCharArray()[i % EncodeKeyString.Length];
                charArray[i] = c;
            }
            int_j = 0;
            for (int i = 0; i < 255; i++)
            {
                int _int_a = intArray[i];
                char _char_a = charArray[i];
                int_j = (int_j + _int_a + _char_a) % 256;

                int _int_tmp = intArray[i];
                intArray[i] = intArray[int_j];
                intArray[int_j] = _int_tmp;
            }
            int_j = 0;
            int_i = 0;
            string value = DataString;

            for (short x = 0; x < DataString.Length; x++)
            {
                int_i = (int_i + 1) % 256;
                int _int_is = intArray[int_i];
                int_j = (int_j + _int_is) % 256;

                int _int_is_i = intArray[int_i];
                int _int_is_j = intArray[int_j];

                int _int_t = (_int_is_i + _int_is_j) % 256;
                int _int_iY = intArray[_int_t];

                char _char_c = DataString.ToCharArray()[x];
                char _char_y = (char)(_char_c ^ _int_iY);


                char[] _char_list = value.ToCharArray();
                _char_list[x] = _char_y;
                String _str = System.Text.Encoding.Unicode.GetString(System.Text.Encoding.Unicode.GetBytes(_char_list));
                value = _str;
            }
            return value;
        }

        /// <summary>
        /// Encrpyts the sourceString, returns this result as an Aes encrpyted, BASE64 encoded string
        /// </summary>
        /// <param name="plainSourceStringToEncrypt">a plain, Framework string (ASCII, null terminated)</param>
        /// <param name="passPhrase">The pass phrase.</param>
        /// <returns>
        /// returns an Aes encrypted, BASE64 encoded string
        /// </returns>
        public static string EncryptString(string plainSourceStringToEncrypt)
        {
            string passPhrase = "wsiosviolet";
            //Set up the encryption objects
            using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passPhrase)))
            {
                byte[] sourceBytes = Encoding.ASCII.GetBytes(plainSourceStringToEncrypt);
                ICryptoTransform ictE = acsp.CreateEncryptor();

                //Set up stream to contain the encryption
                MemoryStream msS = new MemoryStream();

                //Perform the encrpytion, storing output into the stream
                CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write);
                csS.Write(sourceBytes, 0, sourceBytes.Length);
                csS.FlushFinalBlock();

                //sourceBytes are now encrypted as an array of secure bytes
                byte[] encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer

                //return the encrypted bytes as a BASE64 encoded string
                return Convert.ToBase64String(encryptedBytes);
            }
        }


        /// <summary>
        /// Decrypts a BASE64 encoded string of encrypted data, returns a plain string
        /// </summary>
        /// <param name="base64StringToDecrypt">an Aes encrypted AND base64 encoded string</param>
        /// <param name="passphrase">The passphrase.</param>
        /// <returns>returns a plain string</returns>
        public static string DecryptString(string base64StringToDecrypt)
        {
            string passPhrase = "wsiosviolet";
            //Set up the encryption objects
            using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passPhrase)))
            {
                byte[] RawBytes = Convert.FromBase64String(base64StringToDecrypt);
                ICryptoTransform ictD = acsp.CreateDecryptor();

                //RawBytes now contains original byte array, still in Encrypted state

                //Decrypt into stream
                MemoryStream msD = new MemoryStream(RawBytes, 0, RawBytes.Length);
                CryptoStream csD = new CryptoStream(msD, ictD, CryptoStreamMode.Read);
                //csD now contains original byte array, fully decrypted

                //return the content of msD as a regular string
                return (new StreamReader(csD)).ReadToEnd();
            }
        }

        private static AesCryptoServiceProvider GetProvider(byte[] key)
        {
            AesCryptoServiceProvider result = new AesCryptoServiceProvider();
            result.BlockSize = 128;
            result.KeySize = 128;
            result.Mode = CipherMode.CBC;
            result.Padding = PaddingMode.PKCS7;

            result.GenerateIV();
            result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

            byte[] RealKey = GetKey(key, result);
            result.Key = RealKey;
            // result.IV = RealKey;
            return result;
        }

        private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
        {
            byte[] kRaw = suggestedKey;
            List<byte> kList = new List<byte>();

            for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8)
            {
                kList.Add(kRaw[(i / 8) % kRaw.Length]);
            }
            byte[] k = kList.ToArray();
            return k;
        }

        #endregion
    }
}
